home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Archives / GNU / ags_000.lha / gs261gdevilbm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-15  |  12.4 KB  |  470 lines

  1. /* Copyright (C) 1992 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /*
  21.  * gdevilbm.c
  22.  * deepilbm driver for GhostScript
  23.  * this is a straight-forward modification of gdevpbm.c
  24.  * Author: Andreas Heitmann
  25.  */
  26.  
  27. #define DINA4
  28. #define COMPRESSION cmpByteRun1
  29. #define X_DPI 72
  30. #define Y_DPI 72
  31.  
  32. #include <stdio.h>
  33. #include <dos/dos.h>
  34. #include <utility/hooks.h>
  35. #include <libraries/iffparse.h>
  36. #include <clib/iffparse_protos.h>
  37. #include "gdevilbm.h"
  38. #include "gdevprn.h"
  39. #include "gxlum.h"
  40. #include "ilbmpacker.h"
  41.  
  42. struct IFFParseBase *IFFParseBase=NULL;
  43.  
  44. typedef struct gx_device_ilbm_s {
  45.  gx_device_common;
  46.  gx_prn_device_common;
  47.  struct IFFHandle *iff; /* IFF Handle */
  48.  byte palette[256][3];  /* CLUT palette */
  49.  gx_color_index ncols;  /* number of allocated colors in CLUT */
  50.  byte compression;      /* cmpRun || cmpNone */
  51. } ilbm_device;
  52.  
  53. #define ilbm_prn_device(\
  54.  procs,dev_name,\
  55.  num_comp, depth, max_gray, max_rgb,\
  56.  print_page) {\
  57.  prn_device_body(\
  58.   ilbm_device,\
  59.   procs, dev_name,\
  60.   WIDTH_10THS, HEIGHT_10THS, X_DPI, Y_DPI, 0, 0, 0, 0,\
  61.   num_comp, depth, max_gray, max_rgb, max_gray + 1, \
  62.   max_rgb + 1, print_page\
  63.  )\
  64. }
  65.  
  66.  
  67. /* For ILBM we need our own color mapping procedures. */
  68. private dev_proc_map_rgb_color(ilbm24_map_rgb_color);
  69. private dev_proc_map_color_rgb(ilbm24_map_color_rgb);
  70. private dev_proc_print_page(ilbm24_print_page);
  71.  
  72. private dev_proc_map_rgb_color(ilbm8_map_rgb_color);
  73. private dev_proc_map_color_rgb(ilbm8_map_color_rgb);
  74. private dev_proc_print_page(ilbm8_print_page);
  75.  
  76. private dev_proc_output_page(gdev_ilbm_output_page);
  77. private dev_proc_open_device(gdev_ilbm_open);
  78.  
  79. /* The device procedures */
  80. private gx_device_procs ilbm24_procs =
  81. prn_color_procs(
  82.   gdev_ilbm_open,
  83.   gdev_ilbm_output_page,
  84.   gdev_prn_close,
  85.   ilbm24_map_rgb_color,
  86.   ilbm24_map_color_rgb);
  87.  
  88. private gx_device_procs ilbm8_procs =
  89. prn_color_procs(
  90.   gdev_ilbm_open,
  91.   gdev_ilbm_output_page,
  92.   gdev_prn_close,
  93.   ilbm8_map_rgb_color,
  94.   ilbm8_map_color_rgb);
  95.  
  96. /* The device descriptors themselves */
  97. ilbm_device gs_ilbm24_device =
  98. ilbm_prn_device(ilbm24_procs,"ilbm24",3,24,255,255,ilbm24_print_page);
  99.  
  100. ilbm_device gs_ilbm8_device=
  101. ilbm_prn_device(ilbm8_procs,"ilbm8",3,8,31,4,ilbm8_print_page);
  102.  
  103. /* Map an RGB color to a ILBM24 color tuple. */
  104. private gx_color_index
  105. ilbm24_map_rgb_color(gx_device * dev, ushort r, ushort g, ushort b)
  106. {
  107.  return
  108.   (gx_color_value_to_byte(r)<<16)+
  109.   (gx_color_value_to_byte(g)<<8)+
  110.   gx_color_value_to_byte(b);
  111. }
  112.  
  113. /*
  114.  * Map a ILBM24 color tuple back to an RGB color.
  115.  */
  116. private int
  117. ilbm24_map_color_rgb(gx_device * dev, gx_color_index color, ushort prgb[3])
  118. {
  119.  prgb[0] = gx_color_value_from_byte((color>>16)&0xff);
  120.  prgb[1] = gx_color_value_from_byte((color>> 8)&0xff);
  121.  prgb[2] = gx_color_value_from_byte( color     &0xff);
  122.  return 0;
  123. }
  124.  
  125. /*
  126.  * 8-Bit Color-Mapping routines
  127.  * Map an RGB color to a CLUT index
  128.  */
  129. private gx_color_index
  130. ilbm8_map_rgb_color(gx_device *pdev, ushort r, ushort g, ushort b)
  131. {
  132.  byte red_val, green_val, blue_val;
  133.  gx_color_index i;
  134.  static int warn = 1;
  135.  gx_color_index ret = gx_no_color_index;
  136.  
  137.  red_val  =gx_color_value_to_byte(r);
  138.  green_val=gx_color_value_to_byte(g);
  139.  blue_val =gx_color_value_to_byte(b);
  140.  
  141.  /*
  142.   * Look for an exact match among the colors already allocated. This
  143.   * includes the pre-allocated default color cube.
  144.   */
  145.  for (i = 0; i < bdev->ncols; i++) {
  146.   if (bdev->palette[i][0] == red_val &&
  147.       bdev->palette[i][1] == green_val &&
  148.       bdev->palette[i][2] == blue_val) {
  149.    ret = i;
  150.   }
  151.  }
  152.  if (ret==gx_no_color_index) {
  153.   if (bdev->ncols >= (1 <<bdev->color_info.depth)) {
  154.    if (warn) {
  155.     eprintf("gs: last spare color map entry allocated\n");
  156.     warn = 0;
  157.    }
  158.   }
  159.   else {
  160.    bdev->palette[i][0]=red_val;
  161.    bdev->palette[i][1]=green_val;
  162.    bdev->palette[i][2]=blue_val;
  163.    bdev->ncols++;
  164.    ret = i;
  165.   }                /* else alloc new color */
  166.  }                /* end if no spare colors */
  167.  return ret;
  168. }
  169.  
  170. /*
  171.  * Map a CLUT index to an RGB-value
  172.  */
  173. private int
  174. ilbm8_map_color_rgb(gx_device *pdev, gx_color_index color, ushort prgb[3])
  175. {
  176.  prgb[0]=gx_color_value_from_byte(bdev->palette[color][0]);
  177.  prgb[1]=gx_color_value_from_byte(bdev->palette[color][1]);
  178.  prgb[2]=gx_color_value_from_byte(bdev->palette[color][2]);
  179.  return 0;
  180. }
  181.  
  182. /* ------ Individual page printing routines ------ */
  183.  
  184. private int
  185. print_iff_header(gx_device_printer *pdev)
  186. {
  187.  struct BitMapHeader pagebmhd;
  188.  
  189.  PushChunk(bdev->iff,ID_ILBM,ID_BMHD,sizeof(pagebmhd));
  190.  pagebmhd.w=bdev->width;
  191.  pagebmhd.h=bdev->height;
  192.  pagebmhd.x=0;
  193.  pagebmhd.y=0;
  194.  pagebmhd.nPlanes=bdev->color_info.depth;
  195.  pagebmhd.masking=mskNone;
  196.  pagebmhd.compression=bdev->compression;
  197.  pagebmhd.pad1=0;
  198.  pagebmhd.transparentColor=0;
  199.  pagebmhd.xAspect=10;
  200.  pagebmhd.yAspect=10;
  201.  pagebmhd.pageWidth=bdev->width;
  202.  pagebmhd.pageHeight=bdev->height;
  203.  WriteChunkBytes(bdev->iff,&pagebmhd,sizeof(pagebmhd));
  204.  PopChunk(bdev->iff);
  205.  if(bdev->color_info.depth<24) {
  206.   PushChunk(bdev->iff,ID_ILBM,ID_CMAP,3*(1<<bdev->color_info.depth));
  207.   WriteChunkBytes(bdev->iff,bdev->palette,3*(1<<bdev->color_info.depth));
  208.   PopChunk(bdev->iff);
  209.  }
  210. }
  211.  
  212. private int
  213. ilbm8_print_page(gx_device_printer *pdev,FILE *dummy)
  214. {
  215.  const uint outputw=RowBytes(bdev->width);
  216.  const uint line_size=gdev_prn_raster((gx_device_printer *)bdev);
  217.  const uint pack_size=MaxPackedSize(outputw);
  218.  byte *const data  =(byte *)gs_malloc(1,line_size,"ilbm8_print_page");
  219.  byte *const output=(byte *)gs_malloc(8,outputw  ,"ilbm8_print_page");
  220.  byte *const pack  =
  221.   (bdev->compression==cmpByteRun1)
  222.   ?(byte *)gs_malloc(1,pack_size,"ilbm8_print_page"):NULL;
  223.  byte *bp,*planep;
  224.  unsigned long line;
  225.  uint x0,packedbytes;
  226.  byte mask,x1,plane;
  227.  
  228.  if(pack!=NULL||bdev->compression!=cmpByteRun1) {
  229.   if(output!=NULL) {
  230.    if (data != NULL) {
  231.     print_iff_header(pdev);
  232.     PushChunk(bdev->iff,ID_ILBM,ID_BODY,IFFSIZE_UNKNOWN);
  233.     for(line=0;line<bdev->height;line++) {
  234.      gdev_prn_copy_scan_lines((gx_device_printer *)bdev,line,data,line_size);
  235.      memset(output,0,8*outputw);
  236.      planep=output;
  237.      for(mask=1<<0;mask;mask<<=1) {
  238.       bp=data;
  239.       for(x0=outputw;x0;x0--) {
  240.        for(x1=8;x1;x1--) {
  241.     (*planep)<<=1; *planep|=(*bp++&mask)==mask;
  242.        }
  243.        planep++;
  244.       }
  245.      }
  246.      if(bdev->compression==cmpByteRun1) {
  247.       for(plane=bdev->color_info.depth,planep=output;
  248.           plane>0;
  249.       plane--,planep+=outputw) {
  250.        packedbytes=packrow(planep,pack,outputw);
  251.        WriteChunkBytes(bdev->iff,pack,packedbytes); 
  252.       }
  253.      }
  254.      else {
  255.       WriteChunkRecords(bdev->iff,output,outputw,bdev->color_info.depth);
  256.      }
  257.     }
  258.     PopChunk(bdev->iff);    /* Pop Body Chunk */
  259.     gs_free(data,1,line_size,"ilbm8_print_page");
  260.    }
  261.    else  return -1;
  262.    gs_free(output,8,outputw,"ilbm8_print_page");
  263.   }
  264.   else return -1;
  265.   if(bdev->compression==cmpByteRun1) {
  266.    gs_free(pack,1,pack_size,"ilbm8_print_page");
  267.   }
  268.  }
  269.  else return -1;
  270.  return 0;
  271. }
  272.  
  273. /*
  274.  * Print a color-mapped page with 24 Bit
  275.  *
  276.  * This function is too different from ilbm8_print_page, so for
  277.  * higher output speed the main loop is rewritten
  278.  *
  279.  */
  280. private int
  281. ilbm24_print_page(gx_device_printer *pdev,FILE *dummy)
  282. {
  283.  const uint outputw=RowBytes(bdev->width);
  284.  const uint line_size=gdev_prn_raster((gx_device_printer *)bdev);
  285.  const uint pack_size=MaxPackedSize(outputw);
  286.  byte *const data = (byte *)gs_malloc(line_size,1,"ilbm24_print_page");
  287.  byte *const output=(byte *)gs_malloc(24,outputw ,"ilbm24_print_page");
  288.  byte *const pack  =
  289.  (bdev->compression==cmpByteRun1)
  290.  ?(byte *)gs_malloc(1,pack_size,"ilbm8_print_page"):NULL;
  291.  byte *bp,*planep,*red,*green,*blue;
  292.  unsigned long line;
  293.  uint x0,packedbytes;
  294.  byte mask,x1,plane;
  295.  
  296.  if(pack!=NULL||bdev->compression!=cmpByteRun1) {
  297.   if(output!=NULL) {
  298.    if (data != NULL) {
  299.     print_iff_header(pdev);
  300.     PushChunk(bdev->iff,ID_ILBM,ID_BODY,IFFSIZE_UNKNOWN);
  301.     for(line=0;line<bdev->height;line++) {
  302.      gdev_prn_copy_scan_lines((gx_device_printer *)bdev,line,data,line_size);
  303.      memset(output,0,24*outputw);
  304.      red  =output;
  305.      green=red  +8*outputw;
  306.      blue =green+8*outputw;
  307.      for(mask=0;mask<8;mask++) {
  308.       bp=data;
  309.       for(x0=outputw;x0;x0--) {
  310.        for(x1=8;x1;x1--) {
  311.     *red  =*red  <<1|*bp++>>mask&1;
  312.     *green=*green<<1|*bp++>>mask&1;
  313.     *blue =*blue <<1|*bp++>>mask&1;
  314.        }
  315.        red++;
  316.        green++;
  317.        blue++;
  318.       }
  319.      }
  320.      if(bdev->compression==cmpByteRun1) {
  321.       for(plane=bdev->color_info.depth,planep=output;
  322.           plane>0;
  323.       plane--,planep+=outputw) {
  324.        packedbytes=packrow(planep,pack,outputw);
  325.        WriteChunkBytes(bdev->iff,pack,packedbytes); 
  326.       }
  327.      }
  328.      else {
  329.       WriteChunkRecords(bdev->iff,output,outputw,bdev->color_info.depth);
  330.      }
  331.     } /* end for each line */
  332.     PopChunk(bdev->iff);    /* Pop Body Chunk */
  333.     gs_free(data,1,line_size,"ilbm24_print_page");
  334.    }
  335.    else  return -1;
  336.    gs_free(output,8,outputw,"ilbm24_print_page");
  337.   }
  338.   else return -1;
  339.   if(bdev->compression==cmpByteRun1) {
  340.    gs_free(pack,1,pack_size,"ilbm24_print_page");
  341.   }
  342.  }
  343.  else return -1;
  344.  return 0;
  345. }
  346.  
  347. /*
  348.  * Open the current page for printing.
  349.  */
  350. int
  351. gdev_ilbm_open_file(gx_device * pdev)
  352. {
  353.  long ifferror;
  354.  int ret=0;
  355.  char *fname = bdev->fname;
  356.  char pfname[sizeof(bdev->fname) + 10];
  357.  
  358.  if (strchr(fname, '%')) {
  359.   sprintf(pfname, fname, bdev->page_count);
  360.   fname = pfname;
  361.  }
  362.  if(IFFParseBase==NULL) {
  363.   IFFParseBase=(struct IFFParseBase *)OpenLibrary("iffparse.library",33);
  364.   if(IFFParseBase==NULL) {
  365.    eprintf("gdev_ilbm_open_file(): cannot open iffparse.library\n");
  366.    ret=-1;
  367.   }
  368.  }
  369.  if(ret==0) {
  370.   bdev->iff=AllocIFF();
  371.   if(bdev->iff==NULL) {
  372.    eprintf("gdev_ilbm_open_file(): cannot allocate IFFHandle\n");
  373.    ret=-1;
  374.   }
  375.  }
  376.  if(ret==0) {
  377.   bdev->iff->iff_Stream=Open(fname,MODE_NEWFILE);
  378.   if(bdev->iff->iff_Stream==NULL) {
  379.    eprintf1("gdev_ilbm_open_file(): cannot open file %s for writing\n",fname);
  380.    ret=-1;
  381.   }
  382.  }
  383.  if(ret==0) {
  384.   InitIFFasDOS(bdev->iff);
  385.   ifferror=OpenIFF(bdev->iff,IFFF_WRITE);
  386.   if(ifferror!=0) {
  387.    eprintf1("gdev_ilbm_open_file(): iff-error %d\n",ifferror);
  388.    ret=-1;
  389.   }
  390.  }
  391.  if(ret==0) {
  392.   PushChunk(bdev->iff,ID_ILBM,ID_FORM,IFFSIZE_UNKNOWN);
  393.  }
  394.  return ret;
  395. }
  396.  
  397. /*
  398.  * Close the current page.
  399.  */
  400. int
  401. gdev_ilbm_close_file(gx_device *pdev)
  402. {
  403.  /* if (strchr(bdev->fname, '%')) { */
  404.  PopChunk(bdev->iff);        /* Pop FORM chunk */
  405.  CloseIFF(bdev->iff);
  406.  if(bdev->iff->iff_Stream!=NULL) Close((BPTR)bdev->iff->iff_Stream);
  407.  bdev->iff->iff_Stream = NULL;
  408.  FreeIFF(bdev->iff);
  409.  if(IFFParseBase!=NULL) {
  410.   CloseLibrary((struct Library *)IFFParseBase);
  411.   IFFParseBase=NULL;
  412.  }
  413.  /* } */
  414.  return 0;
  415. }
  416.  
  417. /*
  418.  * Generic routine to send the page to the printer.
  419.  *
  420.  * Note that num_copies is currently ignored: this is wrong. 
  421.  */
  422. int
  423. gdev_ilbm_output_page(gx_device *pdev, int num_copies, int flush)
  424. {
  425.  int code;
  426.  
  427.  bdev->page_count++;
  428.  if ((code = gdev_ilbm_open_file(pdev)) >= 0) {
  429.   /* print the accumulated page description */
  430.   if ((code= (*bdev->print_page) ((gx_device_printer *)pdev,NULL)) >= 0) {
  431.    if ((code = gdev_ilbm_close_file(pdev)) >= 0) {
  432.     if (bdev->buffer_space) {   /* reinitialize clist for writing */
  433.      code = (*gs_clist_device_procs.output_page) (pdev, num_copies, 0);
  434.     }
  435.    }
  436.   }
  437.  }
  438.  return code;
  439. }
  440.  
  441.  
  442. int
  443. gdev_ilbm_open(gx_device * pdev)
  444. {
  445.  gdev_prn_open(pdev);
  446.  
  447.  bdev->iff=NULL;
  448.  memset(bdev->palette,0,sizeof(bdev->palette));
  449.  bdev->ncols = 0;
  450.  bdev->compression=COMPRESSION;
  451.  
  452.  if(bdev->color_info.depth==8) { /* CLUT setup */
  453.   gx_color_index color;
  454.   byte r, g, b;
  455.  
  456.   /* allocate black & white as first 2 colors */
  457.   SETRGB(  0,   0,   0);
  458.   SETRGB(255, 255, 255);
  459.  
  460.   /* allocate evenly space color cube */
  461.   while (bdev->ncols < 64) {
  462.    color = bdev->ncols - 1;
  463.    r = (color  & 0x03)    *((1<<bdev->color_info.depth)-1)/(4-1);
  464.    g = ((color & 0x0c)>>2)*((1<<bdev->color_info.depth)-1)/(4-1);
  465.    b = ((color & 0x30)>>4)*((1<<bdev->color_info.depth)-1)/(4-1);
  466.    SETRGB(r, g, b);
  467.   }
  468.  }
  469. }
  470.